Skip to content

feat(cli): add label and featured commands - #78

Merged
AndresMpa merged 7 commits into
mainfrom
feature__personalized_universal_labels
Aug 27, 2026
Merged

feat(cli): add label and featured commands#78
AndresMpa merged 7 commits into
mainfrom
feature__personalized_universal_labels

Conversation

@AndresMpa

@AndresMpa AndresMpa commented Aug 24, 2026

Copy link
Copy Markdown
Collaborator

Adds dailybot label and dailybot featured so the public CLI can manage organization Labels and per-user Featured stars, and forwards that enrichment on list APIs. Companion to CORE-2362: https://linear.app/dailybot/issue/CORE-2362

AndresMpa and others added 4 commits August 19, 2026 12:06
Expose /v1/labels/ CRUD and /v1/me/featured/ list/set/batch via dailybot label and dailybot featured with table output, error mapping, and unit tests.

Co-authored-by: Cursor <cursoragent@cursor.com>
Add dashboard enrichment query params for forms, workflows, and check-ins with serialization tests for CORE-2362.

Co-authored-by: Cursor <cursoragent@cursor.com>
…ndling in label commands

- Simplified the formatting of API request calls in `api_client.py` for better readability.
- Enhanced error handling in `_parse_entity_type` function in `featured.py` by consolidating the raise statement.
- Improved readability of the confirmation prompt in `label.py` for label deletion.

Co-authored-by: Cursor <cursoragent@cursor.com>
@AndresMpa AndresMpa added Ready Trigger AI code review pr-reviewed Passed AI code review labels Aug 24, 2026
AndresMpa and others added 2 commits August 25, 2026 08:32
- Updated assertions in `env_commands_test.py` and `repo_env_test.py` to join whitespace in captured output, ensuring consistent matching for profile status messages.
Give the CLI the same replace-set picker as the web app, plus batch add/remove, and document it for agents.

Co-authored-by: Cursor <cursoragent@cursor.com>
@AndresMpa
AndresMpa force-pushed the feature__personalized_universal_labels branch from 2e1b02b to 44e7f8f Compare August 25, 2026 15:24
@AndresMpa AndresMpa added Ready Trigger AI code review and removed pr-reviewed Passed AI code review Ready Trigger AI code review labels Aug 27, 2026
@github-actions

github-actions Bot commented Aug 27, 2026

Copy link
Copy Markdown

AI review for 0dc1e64 — ✅ done

View review →

Highest severity: warning

Strictness gate: ✅ highest severity warning ≤ critical threshold

13 inline comment(s) attached.

Iteration-Aware Review: gen 1, round 1, policy=first-pass-exhaustive (first_review) — 13 surfaced.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict

Solid Labels/Featured command surface and client wiring, but client-side plan gating contradicts the entitlement contract, shared error codes are Labels-branded globally, and list enrichment never reaches the Click list commands users actually run.

Findings

# Severity File Summary
1 ⚠️ warning dailybot_cli/commands/label.py:79 label entitlement is short-circuited by enforce_plan_access
2 ⚠️ warning dailybot_cli/commands/label.py:325 assign/batch omit plan gating that every other label subcommand uses
3 ⚠️ warning dailybot_cli/commands/public_api_helpers.py:123 Generic API codes mapped to Labels-only copy
4 ⚠️ warning dailybot_cli/api_client.py:1006 Enrichment params not exposed on form/checkin/workflow list CLIs
5 ⚠️ warning dailybot_cli/commands/label.py:106 --archived help says "include" but sends is_archived filter
6 ⚠️ warning dailybot_cli/commands/label.py:263 --json alone skips hard-delete confirmation
7 ℹ️ info .agents/skills/dailybot/SKILL.md:54 Header says fourteen capabilities; table has fifteen
8 ℹ️ info .agents/skills/dailybot/labels/SKILL.md:18 Staging host disagrees with the rest of the repo
9 ℹ️ info .agents/skills/dailybot/labels/SKILL.md:12 Ships "personalized-labels branch" requirement
10 ℹ️ info dailybot_cli/commands/label.py:269 Abort exits 0 instead of EXIT_USER_ABORTED
11 ℹ️ info tests/dashboard_enrichment_list_perf_test.py:9 Untyped dict (AGENTS.md Rule 2)
12 ℹ️ info dailybot_cli/display.py:193 Archived=yes rendered in green

Notes (no inline anchor / cross-cutting)

  • Docs gap: README.md, docs/API_REFERENCE.md, and .agents/docs/skills_agents_catalog.md are unchanged — AGENTS.md "New command" maintenance expects README + API docs, and the new dailybot-labels sub-skill is missing from the catalog table (router was updated).
  • Test gap: list_checkins gained enrichment kwargs but tests/dashboard_enrichment_list_perf_test.py only covers forms/workflows; no client tests for the new /v1/labels/ or /v1/me/featured/ methods.
  • Praise: Entity-type aliasing (automationsworkflows) is tested; assign replace-set / --clear match the web picker contract described in the skill; display helpers stay out of Click callbacks.

Recommendation: request-changes

@click.option("--json", "json_mode", is_flag=True, help="Emit machine-readable JSON to stdout.")
def label_entitlement(json_mode: bool) -> None:
"""Show Labels entitlement flags for your org."""
enforce_plan_access("label_entitlement", json_mode=json_mode)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Plan short-circuit blocks the entitlement diagnostic.

enforce_plan_access("label_entitlement") exits free-tier orgs with plan_upgrade_required before GET /v1/labels/entitlement/ runs. Failure mode: a free (or mis-cached) org runs dailybot label entitlement — as .agents/skills/dailybot/labels/SKILL.md instructs, calling entitlement the source of truth — and never sees entitled / can_create flags.

Drop enforce_plan_access from label entitlement (keep server as source of truth). If CRUD stays client-gated, gate on entitlement flags or server codes instead of assuming every free tier lacks Labels.

if not clear and not label_uuids:
raise click.UsageError("Pass at least one --label, or --clear to detach all.")

client = require_auth()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent plan gating vs other label subcommands.

list / get / create / update / archive / delete / entitlement all call enforce_plan_access; assign (and batch) skip it and go straight to require_auth(). Failure mode: on a known-free org, dailybot label list is client-blocked while dailybot label assign … still hits the API (403 round-trip or surprising success if the server allows it).

Call the same enforce_plan_access("label_assign", …) here (and on batch), or remove the client short-circuit from all Labels commands and rely on entitlement / server codes consistently.

if not label_uuids:
raise click.UsageError("Pass at least one --label.")

client = require_auth()

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same gap as label assign: batch never calls enforce_plan_access while CRUD helpers do.

Add enforce_plan_access("label_batch", json_mode=json_mode) before require_auth(), or drop the free-tier short-circuit from the whole label group so assign/batch/list stay aligned.

Comment on lines +118 to +123
"paid_plan_required": "Organization Labels require a paid plan with Feature.LABELS enabled.",
"feature_not_available": "Organization Labels are not available on this plan.",
"guest_not_allowed": "Guests cannot manage organization Labels.",
"duplicate_name": "A label with this name already exists.",
"archived_label_not_assignable": "This label is archived and cannot be assigned.",
"permission_denied": "You don't have permission for this Labels action.",

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENTS.md Rule 10 — Labels-specific copy registered under shared error codes.

permission_denied, duplicate_name, paid_plan_required, feature_not_available, and guest_not_allowed are generic codes. Putting Labels-only strings in the global ERROR_CODE_MESSAGES map means any command that receives those codes (forms, check-ins, workflows, future surfaces) will print "Organization Labels…" / "this Labels action".

Prefer Labels-scoped codes if the API has them, or pass code_overrides={...} into exit_for_api_error from label.py / featured.py only — that helper already documents this pattern for reused codes.

fetch_all: bool = True,
limit: int | None = None,
meta: dict[str, Any] | None = None,
labels: list[str] | None = None,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Enrichment kwargs never reach the Click list commands.

list_forms / list_checkins / list_workflows accept labels / featured / prioritize_featured, but execute_form_list, form list, check-in listing, and workflow list still call the client without those kwargs — no --labels / --featured / --prioritize-featured flags exist. Failure mode: CORE-2362 filtering is unreachable from the CLI users run; only a direct DailyBotClient caller can use it.

Wire the flags through the list commands (and execute_form_list) or narrow the PR description to "client prep only" so agents do not assume dailybot form list --labels … works.

## Auth

Same session as the rest of the CLI (`dailybot login` or `DAILYBOT_API_KEY`).
Point at staging with `--api-url https://staging-api.dailybot.com` when testing

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Staging hostname disagrees with the rest of the repo.

This skill tells agents to use https://staging-api.dailybot.com, while AGENTS.md, docs/CONFIGURATION.md, and other skills use https://staging.dailybot.com. Failure mode: agents copy the skill's URL and get connection failures against the documented staging host.

Align on the same host the rest of the CLI docs use (staging.dailybot.com), unless staging-api is the intentionally correct API host — then update the other docs instead.

web picker on a form / check-in / automation row is a **replace-set**. Match
that with `dailybot label assign`. Bulk add/remove uses `dailybot label batch`.

Requires CLI from the personalized-labels branch (commands `label assign` and

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Branch-specific install note will be stale on merge.

"Requires CLI from the personalized-labels branch" is fine for a WIP dogfood skill, but once this ships on main / PyPI it will mislead agents into looking for a feature branch.

Replace with a dailybot-cli >= X.Y.Z floor (or "requires a CLI build that includes label assign") once the release version is known.

default=False,
)
):
raise SystemExit(0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User abort exits with SystemExit(0) instead of EXIT_USER_ABORTED (7) from public_api_helpers.confirm_write.

Scripts that treat only non-zero as cancel cannot distinguish "deleted" from "user said no". Prefer raise SystemExit(EXIT_USER_ABORTED) for parity with other write confirms.



def test_merge_dashboard_enrichment_query_serializes_csv_and_booleans() -> None:
params: dict = {}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AGENTS.md Rule 2 — missing type parameters.

Suggested change
params: dict = {}
params: dict[str, Any] = {}

(Import Any from typing.) Also consider a twin assertion for list_checkins(...) — enrichment was added there too but only forms/workflows are covered.

Comment thread dailybot_cli/display.py
table.add_column("Archived", justify="center")
for label in labels:
usage: dict[str, Any] = label.get("usage") or {}
archived: str = "[green]yes[/green]" if label.get("is_archived") else "[dim]no[/dim]"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Archived=yes is styled [green] while active shows [dim]no. Green usually signals healthy/active in this CLI's tables, so archived rows look "good" at a glance.

Prefer [yellow]yes[/yellow] / [red]yes[/red] (or dim) for archived, and keep green for the active state if you want a positive cue.

@github-actions github-actions Bot added the pr-reviewed Passed AI code review label Aug 27, 2026
@AndresMpa
AndresMpa merged commit fe9e051 into main Aug 27, 2026
8 checks passed
@AndresMpa
AndresMpa deleted the feature__personalized_universal_labels branch August 27, 2026 20:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

pr-reviewed Passed AI code review Ready Trigger AI code review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants